#ifndef ALGORITHM__
#define ALGORITHM__

#include "area.h"
#include "options.h"
#include "timer.h"
#include "base.h"

#include <string>
#include <iostream>

/** Abstraktni zakladni trida reprezentujici algoritmus.
 * Slouzi jako zaklad pro tvorbu vsech algoritmu, obsahuje virtualni metody, 
 * ktere je nutne v algoritmech predefinovat (jako napriklad Solve()
 * nebo ruzne vypisy informaci).
 */
class Algorithm {
public:
	/** Defaultni konstruktor.
	 * \param o nastaveni algoritmu
	*/
	Algorithm(Options * o): general(o), area(NULL), timer(new Timer()), frequencies(0) {};
	/** Destruktor. Zrusi ulozene nastaveni. */
	virtual ~Algorithm() {
		delete general;
	}
	/** Vrati sirku vyuziteho pasma.
	 * \return Nejvetsi frekvence - 1
	 */
	int Frequencies() {
		return frequencies - 1;
	}
	/** Vraci, zda je mozne spustit vsechny konfigurace zvoleneho algoritmu. */
	virtual bool AllConfigurations() {
		return false;
	}
	/** Nacte dalsi moznost nastaveni aktualniho algoritmu.
	 * Slouzi ke spusteni vsech typu vypoctu algoritmu (pokud bylo v nastaveni zvoleno, ze se tak ma ucinit).
	 * \return false pokud zadna dalsi konfigurace neexistuje
	 */
	virtual bool Next() {
		return false;
	}
	virtual bool Correct();
	/** Nastavi zadani problemu.*/
	virtual void Set(Area * a) {
		area = a;
	}
	/** Hlavni metoda volana pro vypocet reseni.
	 * \return true pokud vse probehlo v poradku
	 */
	virtual bool Solve() = 0;
	virtual void Print(int * calls = 0);
	virtual void Print(std::ostream & out, int * calls = 0);
	virtual void PrintResult(std::ostream & out);
	virtual void PrintInfo() = 0; ///< Vypise do logu informace o nastaveni algoritmu.
	/** Vrati informace o nastaveni algoritmu.
	 */
	virtual std::string GetDetail() {
		return "";
	}
	/** Vrati informace o nastaveni zadani.
	 */
	std::string AreaDetail() {
		return area->getDetail();
	}
	int RandomNumber(int range, int min = 0);
protected:
	Area * area; ///< mapa problemu
	Timer * timer; ///< casovac pro urcovani doby vypoctu jednotlivych casti
	Options * general; ///< zakladni nastaveni algoritmu
	int frequencies; ///< pocet, se kterymi se aktualne pracuje. Na konci znamena pocet prirazenych frekvenci.
};

#endif
